#ifndef HZ_THREAD_POOL
#define HZ_THREAD_POOL
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <unistd.h>
#include <atomic>
#include <functional>
#include <type_traits>
using namespace std;
class HzThreadPool;

typedef int (*FUNCTYPE)(void *);
class ThreadWorker
{
public:
    using FunPtr = std::function<int(void *)>; // 定义函数指针   返回值为int 参数类型为void*
    /**
     * 构造函数 ->用于接收普通函数指针
     */
    ThreadWorker(FunPtr funptr, void *arg );
    /**
     * 构造函数 ->用于接收成员函数指针
     */
    template <typename Func, typename Obj>
    ThreadWorker(Func func, Obj *obj, void *arg ):arg(arg)
    {
        if (func == NULL)
        {
            std::cerr << "Error: fun is empty." << std::endl;
            funptr = NULL;
            return;
        }
        // 使用 std::is_member_function_pointer 来检查是否是成员函数指针
        if (std::is_member_function_pointer<typename std::remove_pointer<Func>::type>::value)
        {
            if (obj == NULL)
            {
                std::cerr << "Error: obj is empty." << std::endl;
                funptr = NULL;
                return;
            }
        }
        else
        {
            std::cerr << "Error: this is not a member function." << std::endl;
            return;
        }
        funptr = [func, obj](void *arg) -> int
        { return (obj->*func)(arg); };
    }
    /**
     * 检测函数是否有效
     */
    bool IsValid() const;
    /**
     * 开始执行函数
     */
    int operator()();

public:
    FunPtr funptr; // 工作者函数
    void *arg;     // 参数
};

class Thread
{
public:
    Thread(HzThreadPool *pool);

public:
    bool Start();
    bool Stop();
    /*
     * 检测当前线程是否正在运行：
     * true：运行；false：未运行
     */
    bool IsIdle();
    /**
     * 给当前线程分配工作者并唤醒线程进行工作
     */
    void UpdateWorker(ThreadWorker *worker);
    /*
     * 执行线程：
     * 如果m_worker一直没有被分配任务，则一直循环，不会执行
     * 一旦被分配任务，就会执行函数
     */
    void Work();

private:
    HzThreadPool *pool;                     // 线程池，当线程执行完后，通知线程池加入空闲线程
    std::thread m_thread;                   // 当前线程
    bool m_bStatus;              // 线程当前创建状态
    std::mutex mtx;                         // 互斥锁，配合条件变量
    std::condition_variable cv;             // 条件变量，用于唤醒线程
    std::atomic<::ThreadWorker *> m_worker; // 存放一个线程类，主要包括函数(多线程访问，考虑锁的问题)
};

class HzThreadPool
{
public:
    HzThreadPool();
    HzThreadPool(int size);
    ~HzThreadPool();
    // 激活线程池
    bool Invoke();
    // 停止线程池
    void Stop();

public:
    // 返回NULL 表示分配失败，所有线程都在忙 大于等于0，表示第线程指针
    Thread *DispatchWorker(ThreadWorker *worker);

public:
    int size;
    vector<Thread *> threads;
    queue<Thread *> freeThreads;
    mutex m_lock;
    mutex m_push_lock;
};

#endif
